<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>The source code</title>
  <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  <style type="text/css">
    .highlight { display: block; background-color: #ddd; }
  </style>
  <script type="text/javascript">
    function highlight() {
      document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
    }
  </script>
</head>
<body onload="prettyPrint(); highlight();">
  <pre class="prettyprint lang-js"><span id='global-property-S-'>/**
</span> * @fileOverview 表单字段的容器扩展
 * @ignore
 */
var $ = require(&#39;jquery&#39;),
  BUI = require(&#39;bui-common&#39;),
  Field = require(&#39;./field&#39;),
  GroupValid = require(&#39;./groupvalid&#39;),
  PREFIX = BUI.prefix;

var FIELD_XCLASS = &#39;form-field&#39;,
  CLS_FIELD = PREFIX + FIELD_XCLASS,
  CLS_GROUP = PREFIX + &#39;form-group&#39;,
  FIELD_TAGS = &#39;input,select,textarea&#39;;

function isField(node){
  return node.is(FIELD_TAGS);
}
<span id='global-method-getDecorateChilds'>/**
</span> * 获取节点需要封装的子节点
 * @ignore
 */
function getDecorateChilds(node,srcNode){

  if(node != srcNode){

    if(isField(node)){
      return [node];
    }
    var cls = node.attr(&#39;class&#39;);
    if(cls &amp;&amp; (cls.indexOf(CLS_GROUP) !== -1 || cls.indexOf(CLS_FIELD) !== -1)){
      return [node];
    }
  }
  var rst = [],
    children = node.children();
  BUI.each(children,function(subNode){
    rst = rst.concat(getDecorateChilds($(subNode),srcNode));
  });
  return rst;
}

var containerView = BUI.Component.View.extend([GroupValid.View]);

<span id='BUI-Form-FieldContainer'>/**
</span> * 表单字段容器的扩展类
 * @class BUI.Form.FieldContainer
 * @extends BUI.Component.Controller
 * @mixins BUI.Form.GroupValid
 */
var container = BUI.Component.Controller.extend([GroupValid],
  {
    //同步数据
    syncUI : function(){
      var _self = this,
        fields = _self.getFields(),
        validators = _self.get(&#39;validators&#39;);

      BUI.each(fields,function(field){
        var name = field.get(&#39;name&#39;);
        if(validators[name]){
          field.set(&#39;validator&#39;,validators[name]);
        }
      });
      BUI.each(validators,function(item,key){
        //按照ID查找
        if(key.indexOf(&#39;#&#39;) == 0){
          var id = key.replace(&#39;#&#39;,&#39;&#39;),
            child = _self.getChild(id,true);
          if(child){
            child.set(&#39;validator&#39;,item);
          }
        }
      });
    },
<span id='BUI-Form-FieldContainer-method-getDecorateElments'>    /**
</span>     * 获取封装的子控件节点
     * @protected
     * @override
     */
    getDecorateElments : function(){
      var _self = this,
        el = _self.get(&#39;el&#39;);
      var items = getDecorateChilds(el,el);
      return items;
    },
<span id='BUI-Form-FieldContainer-method-findXClassByNode'>    /**
</span>     * 根据子节点获取对应的子控件 xclass
     * @protected
     * @override
     */
    findXClassByNode : function(childNode, ignoreError){


      if(childNode.attr(&#39;type&#39;) === &#39;checkbox&#39;){
        return FIELD_XCLASS + &#39;-checkbox&#39;;
      }

      if(childNode.attr(&#39;type&#39;) === &#39;radio&#39;){
        return FIELD_XCLASS + &#39;-radio&#39;;
      }

      if(childNode.attr(&#39;type&#39;) === &#39;number&#39;){
        return FIELD_XCLASS + &#39;-number&#39;;
      }

      if(childNode.hasClass(&#39;calendar&#39;)){
        return FIELD_XCLASS + &#39;-date&#39;;
      }

      if(childNode[0].tagName == &quot;SELECT&quot;){
        return FIELD_XCLASS + &#39;-select&#39;;
      }

      if(isField(childNode)){
        return FIELD_XCLASS;
      }

      return BUI.Component.Controller.prototype.findXClassByNode.call(this,childNode, ignoreError);
    },
<span id='BUI-Form-FieldContainer-method-getRecord'>    /**
</span>     * 获取表单编辑的对象
     * @return {Object} 编辑的对象
     */
    getRecord : function(){
      var _self = this,
        rst = {},
        fields = _self.getFields();
      BUI.each(fields,function(field){
        var name = field.get(&#39;name&#39;),
          value = _self._getFieldValue(field);

        if(!rst[name]){//没有值，直接赋值
          rst[name] = value;
        }else if(BUI.isArray(rst[name]) &amp;&amp; value != null){//已经存在值，并且是数组，加入数组
          rst[name].push(value);
        }else if(value != null){          //否则封装成数组，并加入数组
          var arr = [rst[name]]
          arr.push(value);
          rst[name] = arr; 
        }
      });
      return rst;
    },
<span id='BUI-Form-FieldContainer-method-getFields'>    /**
</span>     * 获取表单字段
     * @return {Array} 表单字段
     */
    getFields : function(name){
      var _self = this,
        rst = [],
        children = _self.get(&#39;children&#39;);
      BUI.each(children,function(item){
        if(item instanceof Field){
          if(!name || item.get(&#39;name&#39;) == name){
            rst.push(item);
          }
        }else if(item.getFields){
          rst = rst.concat(item.getFields(name));
        }
      });
      return rst;
    },
<span id='BUI-Form-FieldContainer-method-getField'>    /**
</span>     * 根据name 获取表单字段
     * @param  {String} name 字段名
     * @return {BUI.Form.Field}  表单字段或者 null
     */
    getField : function(name){
      var _self = this,
        fields = _self.getFields(),
        rst = null;

      BUI.each(fields,function(field){
        if(field.get(&#39;name&#39;) === name){
          rst = field;
          return false;
        }
      });
      return rst;
    },
<span id='BUI-Form-FieldContainer-method-getFieldAt'>    /**
</span>     * 根据索引获取字段的name
     * @param  {Number} index 字段的索引
     * @return {String}   字段名称
     */
    getFieldAt : function (index) {
      return this.getFields()[index];
    },
<span id='BUI-Form-FieldContainer-method-setFieldValue'>    /**
</span>     * 根据字段名
     * @param {String} name 字段名
     * @param {*} value 字段值
     */
    setFieldValue : function(name,value){
      var _self = this,
        fields = _self.getFields(name);
        BUI.each(fields,function(field){
          _self._setFieldValue(field,value);
        });
    },
    //设置字段域的值
    _setFieldValue : function(field,value){
      //如果字段不可用，则不能设置值
      if(field.get(&#39;disabled&#39;)){
        return;
      }
      //如果是可勾选的
      if(field instanceof Field.Check){
        var fieldValue = field.get(&#39;value&#39;);
        if(value &amp;&amp; (fieldValue === value || (BUI.isArray(value) &amp;&amp; BUI.Array.contains(fieldValue,value)))){
          field.set(&#39;checked&#39;,true);
        }else{
          field.set(&#39;checked&#39;,false);
        }
      }else{
        if(value == null){
          value = &#39;&#39;;
        }
        field.clearErrors(true);//清理错误
        field.set(&#39;value&#39;,value);
      }
    },
<span id='BUI-Form-FieldContainer-method-getFieldValue'>    /**
</span>     * 获取字段值,不存在字段时返回null,多个同名字段时，checkbox返回一个数组
     * @param  {String} name 字段名
     * @return {*}  字段值
     */
    getFieldValue : function(name){
      var _self = this,
        fields = _self.getFields(name),
        rst = [];

      BUI.each(fields,function(field){
        var value = _self._getFieldValue(field);
        if(value){
          rst.push(value);
        }
      });
      if(rst.length === 0){
        return null;
      }
      if(rst.length === 1){
        return rst[0]
      }
      return rst;
    },
    //获取字段域的值
    _getFieldValue : function(field){
      if(!(field instanceof Field.Check) || field.get(&#39;checked&#39;)){
        return field.get(&#39;value&#39;);
      }
      return null;
    },
<span id='BUI-Form-FieldContainer-method-clearFields'>    /**
</span>     * 清除所有表单域的值
     */
    clearFields : function(){
      this.clearErrors(true);
      this.setRecord({})
    },
<span id='BUI-Form-FieldContainer-method-setRecord'>    /**
</span>     * 设置表单编辑的对象
     * @param {Object} record 编辑的对象
     */
    setRecord : function(record){
      var _self = this,
        fields = _self.getFields();

      BUI.each(fields,function(field){
        var name = field.get(&#39;name&#39;);
        _self._setFieldValue(field,record[name]);
      });
    },
<span id='BUI-Form-FieldContainer-method-updateRecord'>    /**
</span>     * 更新表单编辑的对象
     * @param  {Object} record 编辑的对象
     */
    updateRecord : function(record){
      var _self = this,
        fields = _self.getFields();

      BUI.each(fields,function(field){
        var name = field.get(&#39;name&#39;);
        if(record.hasOwnProperty(name)){
          _self._setFieldValue(field,record[name]);
        }
      });
    },
<span id='BUI-Form-FieldContainer-method-focus'>    /**
</span>     * 设置控件获取焦点，设置第一个子控件获取焦点
     */
    focus : function(){
      var _self = this,
        fields = _self.getFields(),
        firstField = fields[0];
      if(firstField){
        firstField.focus();
      }
    },
    //禁用控件
    _uiSetDisabled : function(v){
      var _self = this,
        children = _self.get(&#39;children&#39;);

      BUI.each(children,function(item){
        item.set(&#39;disabled&#39;,v);
      });
    }
  },
  {
    ATTRS : {
<span id='BUI-Form-FieldContainer-property-record'>      /**
</span>       * 表单的数据记录，以键值对的形式存在
       * @type {Object}
       */
      record : {
        setter : function(v){
          this.setRecord(v);
        },
        getter : function(){
          return this.getRecord();
        }
      },
<span id='BUI-Form-FieldContainer-property-validators'>      /**
</span>       * 内部元素的验证函数，可以使用2中选择器
       * &lt;ol&gt;
       *   &lt;li&gt;id: 使用以&#39;#&#39;为前缀的选择器，可以查找字段或者分组，添加联合校验&lt;/li&gt;
       *   &lt;li&gt;name: 不使用任何前缀，没查找表单字段&lt;/li&gt;
       * &lt;/ol&gt;
       * @type {Object}
       */
      validators : {
        value : {

        }
      },
<span id='BUI-Form-FieldContainer-property-defaultLoaderCfg'>      /**
</span>       * 默认的加载控件内容的配置,默认值：
       * &lt;pre&gt;
       *  {
       *   property : &#39;children&#39;,
       *   dataType : &#39;json&#39;
       * }
       * &lt;/pre&gt;
       * @type {Object}
       */
      defaultLoaderCfg  : {
        value : {
          property : &#39;children&#39;,
          dataType : &#39;json&#39;
        }
      },
      disabled : {
        sync : false
      },
      isDecorateChild : {
        value : true
      },
      xview : {
        value : containerView
      }
    }
  },{
    xclass : &#39;form-field-container&#39;
  }
); 
container.View = containerView;

module.exports = container;
</pre>
</body>
</html>
